home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************************
- Align.c
- <http://redshed.net/align>
-
- A buzzard took a monkey for a ride in the air
- The monkey thought that everything was on the square.
- The buzzard tried to throw the monkey off of his back
- But the monkey grabbed his neck and said "Now listen, jack".
-
- Copyright © 1999-2001 Red Shed Software. All rights reserved.
- by Jonathan 'Wolf' Rentzsch (jon@redshed.net)
-
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright notice, this
- list of conditions and the following disclaimer in the documentation and/or other
- materials provided with the distribution.
-
- 3. The names and trademarks of copyright holders may not be used in advertising
- or publicity pertaining to the software without specific prior permission.
-
- This software is provided "as is" and any expressed or implied warranties,
- including, but not limited to, the implied warranties of merchantability and
- fitness for a particular purpose are disclaimed. In no event shall the authors
- or copyright holders be liable for any direct, indirect, incidental, special,
- exemplary, or consequential damages (including, but not limited to, procurement
- of substitute goods or services; loss of use, data, or profits; or business
- interruption) however caused and on any theory of liability, whether in contract,
- strict liability, or tort (including negligence or otherwise) arising in any way
- out of the use of this software, even if advised of the possibility of such
- damage.
-
- Commenter Date Comment
- --------- ----------------- -----------------------------------------------------
- wolf Fri, Feb 12, 1999 Created.
- wolf Mon, Apr 12, 1999 Added AlignX().
- Rewrote Aligned template. Now supports 2, 8 and 16
- byte-aligned data as well as 4.
- wolf Tue, Apr 13, 1999 Rewrote NewAlignedPtr() to take alignment as a
- literal variable instead of a flag. This makes it
- more symmetrical.
- wolf Fri, May 7, 1999 The Aligned template worked well for C data
- structures but contained a flaw for C++ constructed
- objects. The Constructor would be called on the
- non-aligned pointer and then the pointer would be
- aligned (moved). The result would that the
- Constructor operated on the wrong section of memory.
-
- I now align the pointer *and then* call "placement
- new" to call the Constructor on the correct section.
-
- The old Aligned template is still included under the
- name OldAligned.
-
- Broke out Aligned and OldAligned templates into
- their own header file, Aligned.h.
- wolf Mon, Nov 1, 1999 Added AlignDirect_(), which is functionally
- identical to Align_() (where _ is either 2, 4, 8 or
- 16) except it takes a pointer as its parameter and
- returns a pointer. This is unlike Align_(), which
- takes a pointer to a pointer and returns nothing.
- AlignDirect_() makes it possible to declare a
- variable with an initial value
- ("int *x = (int*) AlignDirect_( &alignedX );").
- Used by the new ALIGN macro. By the way,
- AlignDirect_() calls Align_() to do its work.
-
- Added a new macro: ALIGN. It works much like the
- Aligned template except it's a macro, so it works
- under C as well as C++.
- wolf Sat, Jan 22, 2000 Rewrote AlignX() to be faster.
- wolf Sun, Jan 23, 2000 Added Pad typedef.
- wolf Sun, Jan 30, 2000 Carbonized.
- wolf Fri, Feb 18, 2000 Added IsAligned().
- wolf Mon, Dec 11, 2000 Align 1.0.
- wolf Thu, Feb 8, 2001 Align 1.0.2. CodeWarrior Pro 6 breaks an idiom:
- implicit casting of <type>** to void**. I had to make
- all such casts explicit.
-
- ************************************************************************************/
-
- #include "Align.h"
- #include "require.h"
-
- void
- Align2(
- void **ptr )
- {
- RequirePtr( ptr );
- RequirePtr( *ptr );
- (*(long*)ptr) &= 0xFFFFFFFE; // Strip lower bit.
- (*(long*)ptr) += 2; // Move pointer up 2 bytes.
- RequirePtrAlign( *ptr, 2 );
- }
-
- void*
- AlignDirect2(
- void *ptr )
- {
- RequirePtr( ptr );
- Align2( &ptr );
- RequirePtrAlign( ptr, 2 );
- return( ptr );
- }
-
- void
- Align4(
- void **ptr )
- {
- RequirePtr( ptr );
- RequirePtr( *ptr );
- (*(long*)ptr) &= 0xFFFFFFFC; // Strip lower 2 bits.
- (*(long*)ptr) += 4; // Move pointer up 4 bytes.
- RequirePtrAlign( *ptr, 4 );
- }
-
- void*
- AlignDirect4(
- void *ptr )
- {
- RequirePtr( ptr );
- Align4( &ptr );
- RequirePtrAlign( ptr, 4 );
- return( ptr );
- }
-
- void
- Align8(
- void **ptr )
- {
- RequirePtr( ptr );
- RequirePtr( *ptr );
- (*(long*)ptr) &= 0xFFFFFFF8; // Strip lower 3 bits.
- (*(long*)ptr) += 8; // Move pointer up 8 bytes.
- RequirePtrAlign( *ptr, 8 );
- }
-
- void*
- AlignDirect8(
- void *ptr )
- {
- RequirePtr( ptr );
- Align8( &ptr );
- RequirePtrAlign( ptr, 8 );
- return( ptr );
- }
-
- void
- Align16(
- void **ptr )
- {
- RequirePtr( ptr );
- RequirePtr( *ptr );
- (*(long*)ptr) &= 0xFFFFFFF0; // Strip lower 4 bits.
- (*(long*)ptr) += 16; // Move pointer up 16 bytes.
- RequirePtrAlign( *ptr, 16 );
- }
-
- void*
- AlignDirect16(
- void *ptr )
- {
- RequirePtr( ptr );
- Align16( &ptr );
- RequirePtrAlign( ptr, 16 );
- return( ptr );
- }
-
- void
- AlignX(
- void **ptr,
- UInt32 alignment )
- {
- long ptrValue;
-
- RequirePtr( ptr );
- RequirePtr( *ptr );
- Require( alignment == 2 || alignment == 4 || alignment == 8 || alignment == 16 );
-
- ptrValue = (long) *ptr;
- ptrValue &= ~(alignment - 1);
- ptrValue += alignment;
-
- RequirePtrAlign( (void*) ptrValue, alignment );
- *ptr = (void*) ptrValue;
- }
-
- void*
- AlignXDirect(
- void *ptr,
- UInt32 alignment )
- {
- long ptrValue;
-
- RequirePtr( ptr );
- Require( alignment == 2 || alignment == 4 || alignment == 8 || alignment == 16 );
-
- ptrValue = (long) ptr;
- ptrValue &= ~(alignment - 1);
- ptrValue += alignment;
-
- RequirePtrAlign( (void*) ptrValue, alignment );
- return( (void*) ptrValue );
- }
-
- /****************************************************************************************
- Commenter Date Comment
- --------- ----------------- -----------------------------------------------------
- wolf Tue, Apr 13, 1999 Created.
- wolf Fri, May 7, 1999 Added three more requirements and added another
- variable and renamed an existing variable. This was
- done to make the code easier to read.
- wolf Sun, Jan 30, 2000 Carbonized. The fromSystemHeap must always be set to
- false when compiling for Carbon (it's still okay
- for Classic apps).
- wolf Fri, Mar 3, 2000 Now returns a nil pointer upon allocation failure.
-
- ************************************************************************************/
-
- OSErr
- NewAlignedPtr(
- UInt32 size,
- Boolean fromSystemHeap,
- Boolean clearMemory,
- UInt8 alignment,
- void **ptr )
- {
- Ptr macPtr, alignedPtr;
- long *unalignedPtr;
- OSErr err = noErr;
-
- RequireSInt32( size );
- Require( alignment == 4 || alignment == 8 || alignment == 16 );
- RequirePtr( ptr );
-
- // A failure should result in a nil pointer.
- *ptr = nil;
-
- // Bump up the size request to factor in the padding.
- size += alignment;
-
- // Allocate the Ptr as requested.
- #if TARGET_API_MAC_CARBON
- Require( fromSystemHeap == false );
- if( clearMemory )
- macPtr = NewPtrClear( size );
- else
- macPtr = NewPtr( size );
- #else
- if( fromSystemHeap ) {
- macPtr = clearMemory ? NewPtrSysClear( (SInt32) size ) : NewPtrSys( (SInt32) size );
- } else {
- macPtr = clearMemory ? NewPtrClear( (SInt32) size ) : NewPtr( (SInt32) size );
- }
- #endif
- err = MemError();
- // There's a slight possiblity that NewPtr[Sys|Clear|SysClear] will fail,
- // setting macPtr to nil *and* MemError() returning noErr. Here we make sure
- // that a failed Ptr allocation gets an appropriate error code.
- if( !macPtr && !err )
- err = memFullErr;
-
- // Stash the original pointer into the pad zone.
- if( !err ) {
- RequireMacPtr( macPtr );
-
- alignedPtr = macPtr;
- AlignX( (void**) &alignedPtr, alignment );
- unalignedPtr = (long*) alignedPtr;
- --unalignedPtr;
- *unalignedPtr = (long) macPtr;
- *ptr = alignedPtr;
-
- RequireMacPtr( GetUnalignedPtr( *ptr ) );
- Require( GetUnalignedPtr( *ptr ) == macPtr );
- }
-
- return( err );
- }
-
- /****************************************************************************************
- Commenter Date Comment
- --------- ----------------- -----------------------------------------------------
- wolf Wed, Feb 17, 1999 Created.
-
- ************************************************************************************/
-
- Ptr
- GetUnalignedPtr(
- void *ptr )
- {
- long *p = (long*) ptr;
- --p;
- return( (Ptr) *p );
- }
-
- /****************************************************************************************
- Commenter Date Comment
- --------- ----------------- -----------------------------------------------------
- wolf Fri, Feb 18, 2000 Created.
-
- ************************************************************************************/
-
- Boolean
- IsAligned(
- void *ptr,
- UInt8 alignment )
- {
- return( ((long) ptr) % alignment == 0 );
- }